package main
{
	import flash.display.Stage;
	import flash.events.Event;
	import flash.utils.Dictionary;
	
	import loader.AbstractLoader;
	import loader.ModuleLoader;
	
	import modules.*;
	
	import mx.core.IVisualElement;
	
	import spark.components.Application;
	
	import views.*;
	import views.interfaces.IUiBase;
	import views.structure.Structure;
	
	public class ViewMng
	{
		
		private static var _instance:ViewMng;
		
		private var uiModuleMap:Dictionary = new Dictionary();
		
		private var viewMap:Dictionary = new Dictionary();
		
		private var application:Application;
		
		private var structure:Structure;
		
		private var frameProcessors:Dictionary;
		
		private var timerProcessors:Dictionary;
		
		
		public function ViewMng()
		{
			if( _instance )
			{
				throw new Error( "ViewMng it is a sigleton" );
			}
			
		}
		
		public static function instance():ViewMng
		{
			if( !_instance )
			{
				_instance = new ViewMng();
			}
			
			return _instance;
		}
		
		public function init( application:Application ):void
		{
			this.application = application;
			
			structure = new Structure( application.stage, 960, 540 );
			
			application.addElement( structure );
			
			var loadBaseUI:Function = function():void
			{
				showLoading();
				
				show( ScreenView );
			}
				
			initLoadingView( loadBaseUI );
			
		}
		
		
		public function hasUIModule( moduleName:String ):Boolean
		{
			return  uiModuleMap[moduleName] != null;
		}
		
		public function getUIModule( moduleName:String ):UIModuleBase
		{
			return  UIModuleBase( uiModuleMap[moduleName] );
		}
		
		public function loadUIModule( moduleName:String,  callBack:Function ):void
		{
			
			if( !hasUIModule( moduleName ) )
			{
				//var moduleLoader:ModuleLoader = new ModuleLoader();
				
				var complete:Function = function( loaderObj:AbstractLoader ):void
				{	
					uiModuleMap[moduleName] = loaderObj.content;
					
					callBack();
				}
					
				//moduleLoader.startLoad( moduleName, moduleName, progressLoading, complete ); 
					
				LoaderMng.instance().loadModule( moduleName, moduleName, null, complete );
				
			}
			else
			{
				callBack();
			}
			
		}
		
		public function getUIByName( uiName:String ):IUiBase
		{
			var moduleName:String = getModuleNameByUIName( uiName );
			
			if( !moduleName || !hasUIModule( moduleName ) )
			{
				return null;
			}
			
			var module:UIModuleBase = getUIModule( moduleName );
			
			return module.getUIByName( uiName ); 
			
		}
		
		public function getModuleNameByUIName( uiName:String ):String
		{
			for( var key in UIAsset.assetMap )
			{	
				var uiNames:Array = UIAsset.assetMap[ key ] ;
				
				for( var i:int = 0; i < uiNames.length; i++ )
				{
					if( uiNames[i] == uiName )
					{
						return key;
					}
				}
				
			}
			
			return null;
			
		}
		
		
		public function initLoadingView( callback:Function ):void
		{
			loadUIModule( UIAsset.MODULE_LOADING, callback );
		}
		
		public function showLoading():void
		{	
			show( LoadingView );
		}
		
		
		public function progressLoading( desc:String, loadedBytes:int, totalBytes:int, speed:Number,  percent:Number ):void
		{
			loadingView.setProgress( desc, loadedBytes, totalBytes, speed, percent );
		}
		
		public function hideLoading():void
		{
			close( LoadingView );
		}
		
		
		public function show( viewClass:Class ):void
		{	
			if( !viewClass is IView )
			{
				throw new Error( "it must be a IView class" );
			}
			
			var view:IView = getView( viewClass );
			
			if( view.isShowed() )
			{
				return;
			}
			
			if( !view.isInited() )
			{
				var moduleName =   getModuleNameByUIName( view.getUIName() );
				
				if( !moduleName ) return;
				
				if( !hasUIModule( moduleName ) )
				{
					var callBack:Function = function():void
					{
						//hideLoading();
						view.show();	
					}
					
					//showLoading();
					
					loadUIModule( moduleName, callBack );
						
				}
				else
				{
					view.show();
				}
			}
			else
			{
				view.show();
			}
			
		}
		
	
		
		
		public function close( viewClass:Class ):void
		{
			if( !viewClass is IView )
			{
				throw new Error( "it must be a IView class" );
			}
			
			var view:IView = viewMap[ viewClass ];
			
			if( view )
			{
				view.close();
			}
			
		}
		
		public function addContent( uiObj:IUiBase ):void
		{
			structure.addContent( uiObj.content() );
		}
		
		public function addPopup( uiObj:IUiBase ):void
		{
			structure.addPopup( uiObj.content() );
		}
		
		public function removeContent( uiObj:IUiBase ):void
		{
			structure.removeContent( uiObj.content() );
		}
		
		public function removePopup( uiObj:IUiBase ):void
		{
			structure.removePopup( uiObj.content() );
		}
		
		public function center( component:IVisualElement ):void
		{
			component.x = ( application.stage.width - component.width ) / 2;
			component.y = ( application.stage.height - component.height ) / 2;
		}
		
		public function getView( viewClass:Class ):IView
		{
			if( !viewClass is IView )
			{
				throw new Error( "it must be a IView class" );
			}
			
			var view:IView = viewMap[ viewClass ];
			
			if( view == null )
			{
				view = IView( new viewClass() );
				
				viewMap[ viewClass ] = view;
			}
			
			return view;
		}
		
		
		public function get loadingView():LoadingView
		{
			return LoadingView( getView( LoadingView ) );
		}
		
		public function get screenView():ScreenView
		{
			return ScreenView( getView( ScreenView ) );
		}
		
		public function get battleView():BattleView
		{
			return BattleView( getView( BattleView ) );
		}
		
		
		public function hasFrameProcessor( id:String ):Boolean
		{
			return frameProcessors[ id ] != null;
		}
		
		public function putFrameProcessor( id:String, processor:Function ):void
		{
			frameProcessors[ id ] = processor;
		}
		
		public function removeFrameProcessor( id:String ):void
		{
			delete frameProcessors[ id ];
		}
		
		public function onEnterFrame():void
		{
			for( var key:String in frameProcessors )
			{
				var func:Function = frameProcessors[key];
				
				if( func )
				{
					func();
				}
			}
		}
		
		public function hasTimerProcessor( id:String ):Boolean
		{
			return timerProcessors[ id ] != null;
		}
		
		public function putTimerProcessor( id:String, processor:Function ):void
		{
			timerProcessors[ id ] = processor;
		}
		
		public function removeTimerProcessor( id:String ):void
		{
			delete timerProcessors[id];
		}
		
		public function onTimer():void
		{
			for( var key:String in timerProcessors )
			{
				var func:Function = timerProcessors[key];
				
				if( func )
				{
					func();
				}
			}
		}
		
	}
}